// (C) 2021 Intel Corporation. All rights reserved.
// Your use of Intel Corporation's design tools, logic functions and other 
// software and tools, and its AMPP partner logic functions, and any output 
// files from any of the foregoing (including device programming or simulation 
// files), and any associated documentation or information are expressly subject 
// to the terms and conditions of the Intel Program License Subscription 
// Agreement, Intel FPGA IP License Agreement, or other applicable 
// license agreement, including, without limitation, that your use is for the 
// sole purpose of programming logic devices manufactured by Intel and sold by 
// Intel or its authorized distributors.  Please refer to the applicable 
// agreement for further details.

`define KCS_GET_STATUS_ABORT  8'h60
`define KCS_WRITE_START_DATA  8'h61
`define KCS_WRITE_END_DATA    8'h62
`define KCS_READ_NEXT         8'h68

`define KCS_STATE_IDLE  2'h0
`define KCS_STATE_READ  2'h1
`define KCS_STATE_WRITE 2'h2
`define KCS_STATE_UNDEF 2'h3

module espi_kcs_process #(
    parameter DEVICE_FAMILY      = "MAX 10 FPGA"
)(
    input                       clk,
    input                       reset_n,
    input       [31:0]          kcs0_base,
    input                       kcs0_dout_wr,
    input       [7:0]           kcs0_dout,
    output reg  [1:0]           kcs0_status_bit01,
    input                       kcs0_sms_atn,
    output reg                  kcs0_cd,
    output reg                  kcs0_ibf_bmc,
    output                      kcs0_obf_bmc,
    input                       kcs0_din_rd,
    output      [ 7:0]          kcs0_din,
    output reg  [ 7:0]          kcs0_datain_cnt,
    input       [ 7:0]          kcs0_dataout_cnt,

    input       [31:0]          kcs1_base,
    input                       kcs1_dout_wr,
    input       [7:0]           kcs1_dout,
    output reg  [1:0]           kcs1_status_bit01,
    input                       kcs1_sms_atn,
    output reg                  kcs1_cd,
    output reg                  kcs1_ibf_bmc,
    output                      kcs1_obf_bmc,
    input                       kcs1_din_rd,
    output      [ 7:0]          kcs1_din,
    output reg  [ 7:0]          kcs1_datain_cnt,
    input       [ 7:0]          kcs1_dataout_cnt,

    input                       flush_kcs_fifo,
    input                       io_reset,
    input [15:0]                io_address,
    input                       io_write,
    input [7:0]                 io_writedata,
    input                       io_read,
    output reg  [7:0]           io_readdata,
    output logic                io_waitrequest
);

logic       channel_reset_n;

logic       kcs0_din_empty;
logic       kcs0_din_full;
logic       kcs0_dout_empty;
logic       kcs0_dout_full;
logic       kcs0_put_din;
logic [7:0] kcs0_din_wdata;
logic       kcs0_get_dout;
logic       kcs0_get_sts;
logic       kcs0_dout_wr_dly;
logic [7:0] kcs0_dout_wdata;
logic       kcs0_put_dout;
logic [7:0] kcs0_status_internal;
logic       kcs0_obf_int;
logic       kcs0_ibf_int;
logic [7:0] kcs0_dout_rdata;
logic       kcs0_rd_req;
logic       kcs0_addr_equal_base15to0;
logic       kcs0_addr_equal_base31to16;
logic       kcs0_data_equal_start;
logic       kcs0_data_equal_end;
logic [7:0] kcs0_din_rdata;
logic       flg_kcs0_wr_start;
logic       flg_kcs0_wr_req;
logic       flg_kcs0_last_wr_req;
logic       flg_kcs0_rd_req;
logic       flg_kcs0_rd_req_1d;
logic       re_flg_kcs0_rd_req;
logic       flg_kcs0_rd_sts;
logic       get_kcs0_din;
logic       kcs0_rd_sts_done;
logic       kcs0_get_sts_d1;
logic       kcs0_last_wr_done;
logic       kcs0_last_wr_period;
logic       kcs0_last_wr_period_d;
logic [7:0] kcs0_rd_cnt;
logic [7:0] kcs0_dout2bios;



logic       kcs1_din_empty;
logic       kcs1_din_full;
logic       kcs1_dout_empty;
logic       kcs1_dout_full;
logic       kcs1_put_din;
logic [7:0] kcs1_din_wdata;
logic       kcs1_get_dout;
logic       kcs1_get_sts;
logic       kcs1_dout_wr_dly;
logic [7:0] kcs1_dout_wdata;
logic       kcs1_put_dout;
logic [7:0] kcs1_status_internal;
logic       kcs1_obf_int;
logic       kcs1_ibf_int;
logic [7:0] kcs1_dout_rdata;
logic       kcs1_rd_req;
logic       kcs1_addr_equal_base15to0;
logic       kcs1_addr_equal_base31to16;
logic       kcs1_data_equal_start;
logic       kcs1_data_equal_end;
logic [7:0] kcs1_din_rdata;
logic       flg_kcs1_wr_start;
logic       flg_kcs1_wr_req;
logic       flg_kcs1_last_wr_req;
logic       flg_kcs1_rd_req;
logic       flg_kcs1_rd_req_1d;
logic       re_flg_kcs1_rd_req;
logic       flg_kcs1_rd_sts;
logic       get_kcs1_din;
logic       kcs1_rd_sts_done;
logic       kcs1_get_sts_d1;
logic       kcs1_last_wr_done;
logic       kcs1_last_wr_period;
logic       kcs1_last_wr_period_d;
logic [7:0] kcs1_rd_cnt;
logic [7:0] kcs1_dout2bios;


logic       kcs0_rd_en;
logic       kcs1_rd_en;

logic       flg_kcs0_r_doutfifo_done;
logic       flg_kcs1_r_doutfifo_done;
logic       flg_kcs0_rcv_cmd_w68;
logic       flg_kcs1_rcv_cmd_w68;
logic       kcs0_data_equal_68;
logic       kcs1_data_equal_68;

assign channel_reset_n = ~io_reset;

logic io_read_1;
logic io_read_accepted;

always @(posedge clk)
begin
   io_read_1 <= io_read;
   if(kcs0_get_sts)
       io_readdata <= kcs0_status_internal;
   else if(kcs1_get_sts)
       io_readdata <= kcs1_status_internal;
   else if(kcs0_rd_req)
       io_readdata <= kcs0_dout2bios;
   else if(kcs1_rd_req)
       io_readdata <= kcs1_dout2bios;
   else
       io_readdata <= 8'd0;
end

assign io_waitrequest   = io_read & ~io_read_1;
assign io_read_accepted = io_read & ~io_waitrequest;

assign kcs0_addr_equal_base15to0  = (io_address == kcs0_base[15:0]);
assign kcs0_addr_equal_base31to16 = (io_address == kcs0_base[31:16]);
assign kcs0_data_equal_start      = (io_writedata==`KCS_WRITE_START_DATA);
assign kcs0_data_equal_end        = (io_writedata==`KCS_WRITE_END_DATA);
assign kcs0_data_equal_68         = (io_writedata==`KCS_READ_NEXT);

assign flg_kcs0_wr_start    = io_write & kcs0_addr_equal_base15to0  & kcs0_data_equal_start;
assign flg_kcs0_wr_req      = io_write & kcs0_addr_equal_base31to16;
assign flg_kcs0_last_wr_req = io_write & kcs0_addr_equal_base15to0  & kcs0_data_equal_end;
assign flg_kcs0_rd_req      = io_read_accepted  & kcs0_addr_equal_base31to16;
assign flg_kcs0_rd_sts      = io_read_accepted  & kcs0_addr_equal_base15to0;
assign flg_kcs0_rcv_cmd_w68 = io_write & kcs0_addr_equal_base31to16 & kcs0_data_equal_68;
assign re_flg_kcs0_rd_req   = flg_kcs0_rd_req & ~flg_kcs0_rd_req_1d;

assign kcs0_status_internal = {kcs0_status_bit01,2'b00,kcs0_cd,kcs0_sms_atn,kcs0_ibf_int,kcs0_obf_int};
assign kcs0_obf_bmc         = kcs0_dout_full;

always @(posedge clk or negedge channel_reset_n)
begin
    if(!channel_reset_n)
        flg_kcs0_r_doutfifo_done <= 1'b0;
    else if(kcs0_get_dout)
        flg_kcs0_r_doutfifo_done <= 1'b1;
    else if(flg_kcs0_rcv_cmd_w68)
        flg_kcs0_r_doutfifo_done <= 1'b0;
end

always @(posedge clk)
begin
    kcs0_get_dout  <= (kcs0_rd_cnt<=kcs0_dataout_cnt)&&
                      (kcs0_rd_req && (kcs0_rd_en )
                       && ~kcs0_dout_empty) && (~flg_kcs0_r_doutfifo_done);
end
// track when kcs0_get_dout skips due to fifo empty
reg kcs0_rd_en_clr = 1'b0;
always @(posedge clk)
begin
    kcs0_rd_en_clr <= (kcs0_rd_cnt>=kcs0_dataout_cnt)&& kcs0_rd_req && kcs0_rd_en;
end

always @(posedge clk or negedge channel_reset_n)
begin
    if(!channel_reset_n)
        kcs0_rd_en <= 1'b0;
    else if(flg_kcs0_rd_req && (kcs0_status_bit01!=`KCS_STATE_WRITE))
        kcs0_rd_en <= 1'b1;
    else if(kcs0_get_dout)
        kcs0_rd_en <= 1'b0;
    else if(kcs0_rd_en_clr)
        kcs0_rd_en <= 1'b0;
end

always @(posedge clk or negedge channel_reset_n)
begin
    if(!channel_reset_n)
         kcs0_rd_cnt <= 8'd0;
    else if(kcs0_status_bit01==`KCS_STATE_READ)  //read
         kcs0_rd_cnt <= kcs0_rd_cnt + kcs0_get_dout;
    else if(kcs0_status_bit01==`KCS_STATE_IDLE) //idle read dummy data
         kcs0_rd_cnt <= kcs0_rd_cnt + re_flg_kcs0_rd_req;
    else if(kcs0_status_bit01==`KCS_STATE_WRITE) //write
         kcs0_rd_cnt <= 8'd0;
end

always @(posedge clk or negedge channel_reset_n)
begin
    if(!channel_reset_n)
        kcs0_obf_int <= 1'b0;
    else if((kcs0_status_bit01==`KCS_STATE_READ)&& |kcs0_dataout_cnt)     //read
        kcs0_obf_int <= 1'b1;
    else if((kcs0_status_bit01==`KCS_STATE_IDLE)&&(kcs0_rd_cnt==(kcs0_dataout_cnt+8'd1)))  //idle
        kcs0_obf_int <= 1'b0;
end


always @(posedge clk)
begin
    kcs0_get_sts_d1 <= kcs0_get_sts;
    kcs0_rd_sts_done <= kcs0_get_sts_d1 && (~kcs0_get_sts);

    kcs0_last_wr_period_d <= kcs0_last_wr_period;
    kcs0_last_wr_done <= kcs0_last_wr_period_d &&(~kcs0_last_wr_period);
end

always @(posedge clk)
begin
    if(kcs0_status_bit01==`KCS_STATE_UNDEF)  //idle status
        kcs0_ibf_bmc <= 1'b0;
    else if(kcs0_last_wr_done)
        kcs0_ibf_bmc <= 1'b1;
    else if(kcs0_din_empty)
        kcs0_ibf_bmc <= 1'b0;
end

always @(posedge clk or negedge channel_reset_n)
begin
    if(!channel_reset_n)
        kcs0_last_wr_period <= 1'b0;
    else if(flg_kcs0_last_wr_req)
        kcs0_last_wr_period <= 1'b1;
    else if(flg_kcs0_wr_req)
        kcs0_last_wr_period <= 1'b0;
end
always @(posedge clk or negedge channel_reset_n)
begin
    if(!channel_reset_n)
        kcs0_status_bit01 <= `KCS_STATE_UNDEF;
    else if(kcs0_rd_sts_done && (kcs0_status_bit01==`KCS_STATE_UNDEF))//idle
        kcs0_status_bit01 <= `KCS_STATE_IDLE;
    else if(flg_kcs0_wr_start &&(kcs0_status_bit01==`KCS_STATE_IDLE))//write
        kcs0_status_bit01 <= `KCS_STATE_WRITE;
    else if(kcs0_last_wr_done && (kcs0_status_bit01==`KCS_STATE_WRITE))//read
        kcs0_status_bit01 <= `KCS_STATE_READ;
    else if((kcs0_rd_cnt==kcs0_dataout_cnt)&&(kcs0_rd_cnt != 8'd0)&&(kcs0_status_bit01==`KCS_STATE_READ)&&(flg_kcs0_rcv_cmd_w68))
        kcs0_status_bit01 <= `KCS_STATE_IDLE;
end

always @(posedge clk or negedge channel_reset_n)
begin
    if(!channel_reset_n)
        kcs0_datain_cnt <= 8'd0;
    else if(flg_kcs0_wr_start &&(kcs0_status_bit01==`KCS_STATE_IDLE))
        kcs0_datain_cnt <= 8'd0;
    else if(flg_kcs0_wr_req&&(kcs0_status_bit01==`KCS_STATE_WRITE))
        kcs0_datain_cnt <= kcs0_datain_cnt + 8'd1;
end

always @(posedge clk)
begin
    if((kcs0_rd_cnt==8'd0)&&(kcs0_status_bit01==`KCS_STATE_WRITE))
       kcs0_dout2bios <= 8'd0;
    else if(kcs0_rd_cnt<kcs0_dataout_cnt)
       kcs0_dout2bios <= kcs0_dout_rdata;
    // Force data out to 0x00 after last byte is read from dout fifo (dummy data = 0x00)
    else
       kcs0_dout2bios <= 8'd0;
end

always @(posedge clk or negedge channel_reset_n)
begin
    if(!channel_reset_n)
        kcs0_cd <= 1'b0;
    else if(flg_kcs0_wr_start||flg_kcs0_last_wr_req)
        kcs0_cd <= 1'b1;
    else if(flg_kcs0_wr_req)
        kcs0_cd <= 1'b0;
end

assign kcs0_ibf_int = kcs0_din_full;

always @(posedge clk)
begin
    kcs0_put_din   <= flg_kcs0_wr_req && (kcs0_status_bit01==`KCS_STATE_WRITE);
    kcs0_din_wdata <= flg_kcs0_wr_req ? io_writedata:8'd0;
    flg_kcs0_rd_req_1d <= flg_kcs0_rd_req;
end

    assign kcs0_get_sts = flg_kcs0_rd_sts;
    assign kcs0_rd_req = flg_kcs0_rd_req;


assign get_kcs0_din = kcs0_din_rd;
assign kcs0_din = kcs0_din_rdata;

kcs_fifo #(
    .DSIZE  (8),
    .DEPTH  (512),
    .WIDTHU (9),
    .FAMILY (DEVICE_FAMILY)
) kcs0_datain_inst (
    .clk          (clk),
    .rst_n        (channel_reset_n && ~flush_kcs_fifo),
    .put          (kcs0_put_din),
    .get          (get_kcs0_din),
    .wdata        (kcs0_din_wdata),
    .full         (kcs0_din_full),
    .empty        (kcs0_din_empty),
    .rdata        (kcs0_din_rdata),
    .usedw        ()
);

kcs_fifo #(
    .DSIZE  (8),
    .DEPTH  (512),
    .WIDTHU (9),
    .FAMILY (DEVICE_FAMILY)
) kcs0_dataout_inst (
    .clk          (clk),
    .rst_n        (channel_reset_n && ~flush_kcs_fifo),
    .put          (kcs0_put_dout),
    .get          (kcs0_get_dout),
    .wdata        (kcs0_dout_wdata),
    .full         (kcs0_dout_full),
    .empty        (kcs0_dout_empty),
    .rdata        (kcs0_dout_rdata),
    .usedw        ()
);

always @(posedge clk)
begin
    kcs0_dout_wr_dly <= kcs0_dout_wr;
    kcs0_put_dout <= {kcs0_dout_wr_dly,kcs0_dout_wr}==2'b01;
    kcs0_dout_wdata <= kcs0_dout;
end

//////////////////////////////////////////////////////////////////////
assign kcs1_addr_equal_base15to0  = (io_address == kcs1_base[15:0]);
assign kcs1_addr_equal_base31to16 = (io_address == kcs1_base[31:16]);
assign kcs1_data_equal_start      = (io_writedata==`KCS_WRITE_START_DATA);
assign kcs1_data_equal_end        = (io_writedata==`KCS_WRITE_END_DATA);
assign kcs1_data_equal_68         = (io_writedata==`KCS_READ_NEXT);

assign flg_kcs1_wr_start    = io_write & kcs1_addr_equal_base15to0  & kcs1_data_equal_start;
assign flg_kcs1_wr_req      = io_write & kcs1_addr_equal_base31to16;
assign flg_kcs1_last_wr_req = io_write & kcs1_addr_equal_base15to0  & kcs1_data_equal_end;
assign flg_kcs1_rd_req      = io_read_accepted & kcs1_addr_equal_base31to16;
assign flg_kcs1_rd_sts      = io_read_accepted & kcs1_addr_equal_base15to0;
assign flg_kcs1_rcv_cmd_w68 = io_write & kcs1_addr_equal_base31to16 & kcs1_data_equal_68;
assign re_flg_kcs1_rd_req   = flg_kcs1_rd_req & ~flg_kcs1_rd_req_1d;

assign kcs1_status_internal = {kcs1_status_bit01,2'b00,kcs1_cd,kcs1_sms_atn,kcs1_ibf_int,kcs1_obf_int};
assign kcs1_obf_bmc         = kcs1_dout_full;

always @(posedge clk or negedge channel_reset_n)
begin
    if(!channel_reset_n)
        flg_kcs1_r_doutfifo_done <= 1'b0;
    else if(kcs1_get_dout)
        flg_kcs1_r_doutfifo_done <= 1'b1;
    else if(flg_kcs1_rcv_cmd_w68)
        flg_kcs1_r_doutfifo_done <= 1'b0;
end
always @(posedge clk)
begin
    kcs1_get_dout       <= (kcs1_rd_cnt<=kcs1_dataout_cnt)&&
                           (kcs1_rd_req && (kcs1_rd_en )
                              && ~kcs1_dout_empty) && (~flg_kcs1_r_doutfifo_done);
end
// track when kcs1_get_dout skips due to fifo empty
reg kcs1_rd_en_clr = 1'b0;
always @(posedge clk)
begin
    kcs1_rd_en_clr <= (kcs1_rd_cnt>=kcs1_dataout_cnt)&& kcs1_rd_req && kcs1_rd_en;
end


always @(posedge clk or negedge channel_reset_n)
begin
    if(!channel_reset_n)
        kcs1_rd_en <= 1'b0;
    else if(flg_kcs1_rd_req && (kcs1_status_bit01!=`KCS_STATE_WRITE))
        kcs1_rd_en <= 1'b1;
    else if(kcs1_get_dout)
        kcs1_rd_en <= 1'b0;
    else if(kcs1_rd_en_clr)
        kcs1_rd_en <= 1'b0;
end

always @(posedge clk or negedge channel_reset_n)
begin
    if(!channel_reset_n)
         kcs1_rd_cnt <= 8'd0;
    else if(kcs1_status_bit01==`KCS_STATE_READ)  //read
         kcs1_rd_cnt <= kcs1_rd_cnt + kcs1_get_dout;
    else if(kcs1_status_bit01==`KCS_STATE_IDLE) //idle read dummy data
         kcs1_rd_cnt <= kcs1_rd_cnt + re_flg_kcs1_rd_req;
    else if(kcs1_status_bit01==`KCS_STATE_WRITE) //write
         kcs1_rd_cnt <= 8'd0;
end

always @(posedge clk or negedge channel_reset_n)
begin
    if(!channel_reset_n)
        kcs1_obf_int <= 1'b0;
    else if((kcs1_status_bit01==`KCS_STATE_READ)&& |kcs1_dataout_cnt)
        kcs1_obf_int <= 1'b1;
    else if((kcs1_status_bit01==`KCS_STATE_IDLE)&&(kcs1_rd_cnt==(kcs1_dataout_cnt+8'd1)))  //idle
        kcs1_obf_int <= 1'b0;
end


always @(posedge clk)
begin
    kcs1_get_sts_d1 <= kcs1_get_sts;
    kcs1_rd_sts_done <= kcs1_get_sts_d1 && (~kcs1_get_sts);

    kcs1_last_wr_period_d <= kcs1_last_wr_period;
    kcs1_last_wr_done <= kcs1_last_wr_period_d &&(~kcs1_last_wr_period);
end

always @(posedge clk)
begin
    if(kcs1_status_bit01==`KCS_STATE_UNDEF)  //idle status
        kcs1_ibf_bmc <= 1'b0;
    else if(kcs1_last_wr_done)
        kcs1_ibf_bmc <= 1'b1;
    else if(kcs1_din_empty)
        kcs1_ibf_bmc <= 1'b0;
end

always @(posedge clk or negedge channel_reset_n)
begin
    if(!channel_reset_n)
        kcs1_last_wr_period <= 1'b0;
    else if(flg_kcs1_last_wr_req)
        kcs1_last_wr_period <= 1'b1;
    else if(flg_kcs1_wr_req)
        kcs1_last_wr_period <= 1'b0;
end
always @(posedge clk or negedge channel_reset_n)
begin
    if(!channel_reset_n)
        kcs1_status_bit01 <= `KCS_STATE_UNDEF;
    else if(kcs1_rd_sts_done && (kcs1_status_bit01==`KCS_STATE_UNDEF))//idle
        kcs1_status_bit01 <= `KCS_STATE_IDLE;
    else if(flg_kcs1_wr_start &&(kcs1_status_bit01==`KCS_STATE_IDLE))//write
        kcs1_status_bit01 <= `KCS_STATE_WRITE;
    else if(kcs1_last_wr_done && (kcs1_status_bit01==`KCS_STATE_WRITE))//read
        kcs1_status_bit01 <= `KCS_STATE_READ;
    else if((kcs1_rd_cnt==kcs1_dataout_cnt)&&(kcs1_rd_cnt != 8'd0)&&(kcs1_status_bit01==`KCS_STATE_READ)&&(flg_kcs1_rcv_cmd_w68))
        kcs1_status_bit01 <= `KCS_STATE_IDLE;
end

always @(posedge clk or negedge channel_reset_n)
begin
    if(!channel_reset_n)
        kcs1_datain_cnt <= 8'd0;
    else if(flg_kcs1_wr_start &&(kcs1_status_bit01==`KCS_STATE_IDLE))
        kcs1_datain_cnt <= 8'd0;
    else if(flg_kcs1_wr_req&&(kcs1_status_bit01==`KCS_STATE_WRITE))
        kcs1_datain_cnt <= kcs1_datain_cnt + 8'd1;
end

always @(posedge clk)
begin
    if((kcs1_rd_cnt==8'd0)&&(kcs1_status_bit01==`KCS_STATE_WRITE))
       kcs1_dout2bios <= 8'd0;
    else if(kcs1_rd_cnt<kcs1_dataout_cnt)
       kcs1_dout2bios <= kcs1_dout_rdata;
    // Force data out to 0x00 after last byte is read from dout fifo (dummy data = 0x00)
    else
       kcs1_dout2bios <= 8'd0;
end


always @(posedge clk or negedge channel_reset_n)
begin
    if(!channel_reset_n)
        kcs1_cd <= 1'b0;
    else if(flg_kcs1_wr_start||flg_kcs1_last_wr_req)
        kcs1_cd <= 1'b1;
    else if(flg_kcs1_wr_req)
        kcs1_cd <= 1'b0;
end

assign kcs1_ibf_int = kcs1_din_full;

always @(posedge clk)
begin
    kcs1_put_din   <= flg_kcs1_wr_req && (kcs1_status_bit01==`KCS_STATE_WRITE);
    kcs1_din_wdata <= flg_kcs1_wr_req ? io_writedata:8'd0;
    flg_kcs1_rd_req_1d <= flg_kcs1_rd_req;
end

    assign kcs1_get_sts = flg_kcs1_rd_sts;
    assign kcs1_rd_req = flg_kcs1_rd_req;


assign get_kcs1_din = kcs1_din_rd;
assign kcs1_din = kcs1_din_rdata;

kcs_fifo #(
    .DSIZE  (8),
    .DEPTH  (512),
    .WIDTHU (9),
    .FAMILY (DEVICE_FAMILY)
) kcs1_datain_inst (
    .clk          (clk),
    .rst_n        (channel_reset_n && ~flush_kcs_fifo),
    .put          (kcs1_put_din),
    .get          (get_kcs1_din),
    .wdata        (kcs1_din_wdata),
    .full         (kcs1_din_full),
    .empty        (kcs1_din_empty),
    .rdata        (kcs1_din_rdata),
    .usedw        ()
);

kcs_fifo #(
    .DSIZE  (8),
    .DEPTH  (512),
    .WIDTHU (9),
    .FAMILY (DEVICE_FAMILY)
) kcs1_dataout_inst (
    .clk          (clk),
    .rst_n        (channel_reset_n && ~flush_kcs_fifo),
    .put          (kcs1_put_dout),
    .get          (kcs1_get_dout),
    .wdata        (kcs1_dout_wdata),
    .full         (kcs1_dout_full),
    .empty        (kcs1_dout_empty),
    .rdata        (kcs1_dout_rdata),
    .usedw        ()
);

always @(posedge clk)
begin
    kcs1_dout_wr_dly <= kcs1_dout_wr;
    kcs1_put_dout <= {kcs1_dout_wr_dly,kcs1_dout_wr}==2'b01;
    kcs1_dout_wdata <= kcs1_dout;
end
endmodule
